package lucene;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Scanner;
import java.util.Vector;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.util.CharArraySet;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.DocsAndPositionsEnum;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.Version;

public class StoredFile implements Serializable{
    
    private ArrayList<String> versionList;
    private String currentVers;
    private int counter;
    private File data;
    private String diskPath;
    
    StoredFile(File fl, String path)
    {
        this.versionList = new ArrayList<>();
        this.counter = 1;
        this.versionList.add("1");
        this.currentVers = this.versionList.get(0);
        this.data = fl;
        this.diskPath = path;
    }
    
    /*
    Copy constructor
    */
    StoredFile(StoredFile fl)
    {
        this.versionList = fl.versionList;
        this.counter = fl.counter;
        this.currentVers = fl.currentVers;
        this.data = fl.data;
    }
    
    public void addVersion()
    {
        this.counter++;
        this.versionList.add(data.toString().substring(0, data.toString().lastIndexOf("\\"))+"\\"+Integer.toString(counter));
    }
    
    private void deleteDirectory(File file) {
		if(!file.exists())
			return;
		if(file.isDirectory()) {
			for(File f : file.listFiles()) {
				f.delete();
				System.out.println("am sters "+f.toString());
			}
		}
		file.delete();
	}
    
    public void removeVersion()
    {
    	
    	File fc = new File(data.toString());
    	File dir = new File(data.toString().substring(0, data.toString().lastIndexOf("\\"))+"\\"+Integer.toString(counter));
		deleteDirectory(dir);
        
        this.versionList.remove(data.toString().substring(0, data.toString().lastIndexOf("\\"))+"\\"+Integer.toString(counter));        
        this.counter--;
    }
    
    public void setVersion(String vers)
    {
        //apeleaza codul pt highlights
    }
    
    public String getVersion(){
        return Integer.toString(counter);
    }   
    
    public void resetFile(StoredFile fl)
    {
        //copy constructor
        StoredFile reset = new StoredFile(fl);
    }
    
    public String getName()
    {
    	System.out.println(currentVers);
    	System.out.println(counter);
    	System.out.println(data);
    	System.out.println(diskPath);
        return this.data.getName();
    }
    
    public String getDiskPath() {
    	return diskPath;
    }
    
    
    public File getData() {
    	return data;
    }
    
    
    public ArrayList<String> versionList()
    {
        return this.versionList;
    }
    
    public void updateLists(int version) throws IOException {
    	System.out.println("update la "+version);
    	HashMap<Integer,String> versiuneVeche = new HashMap();
    	HashMap<Integer,String> versiuneCurenta = new HashMap();
        String indexLocation1;
        String indexLocation2;
        
        
        indexLocation1 = data.getAbsolutePath().substring(0,data.getAbsolutePath().lastIndexOf("\\"))+"\\"+Integer.toString(version);
        indexLocation2 = versionList.get(counter-1);
        
System.out.println(indexLocation1);
System.out.println(indexLocation2);
        


            IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(
                            indexLocation1)));
            int docId = reader.getDocCount(indexLocation1);
        int length = 0;
        Terms vector = reader.getTermVector(docId, "contents");
        TermsEnum termsEnum = null;
        termsEnum = vector.iterator(termsEnum);
        HashMap<Integer, String> curent = new HashMap<>();
        BytesRef text = null;
        Vector<String> terms =new Vector();
        while ((text = termsEnum.next()) != null) {
            String term = text.utf8ToString();
            int freq = (int) termsEnum.totalTermFreq();
            DocsAndPositionsEnum docPosEnum = termsEnum.docsAndPositions(null, null, DocsAndPositionsEnum.FLAG_OFFSETS);
            docPosEnum.nextDoc();
            //Retrieve the term frequency in the current document
            freq=docPosEnum.freq();
            for(int j=0; j<freq; j++){
                int position=docPosEnum.nextPosition();
                curent.put(position, term);
            }            
    }
        reader.close();
        

    IndexReader reader1 = DirectoryReader.open(FSDirectory.open(new File(
                            indexLocation2)));

            int docId1 = reader1.getDocCount(indexLocation1);
            Terms vector1 = reader1.getTermVector(docId1, "contents");
            TermsEnum termsEnum1 = null;
            termsEnum1 = vector1.iterator(termsEnum);
            HashMap<Integer, String> old = new HashMap<>();
            BytesRef text1 = null;
            Vector<String> terms1 = new Vector();

            while ((text1 = termsEnum1.next()) != null) {
                    String term1 = text1.utf8ToString();
                    int freq1 = (int) termsEnum1.totalTermFreq();
                    DocsAndPositionsEnum docPosEnum1 = termsEnum.docsAndPositions(null,
                                    null, DocsAndPositionsEnum.FLAG_OFFSETS);
                    docPosEnum1.nextDoc();
                    // Retrieve the term frequency in the current document
                    freq1 = docPosEnum1.freq();
                    for(int j=0; j<freq1; j++){
			            int position=docPosEnum1.nextPosition();
			            old.put(position, term1);
                    }    
            }

            reader1.close();
            /*
            for(int i=0;i<curent.size()+1;i++) {
                    System.out.println(curent.get(i));
            }
            System.out.println("--------------------");
            for(int i=0;i<old.size();i++) {
                    System.out.println(old.get(i));
            }
            */

            int n;
    if(curent.size() >old.size()) {
            n = curent.size();
    } else {
            n = old.size();
    }


    int i1;
    int i2;
    int i3;
    int k1 = 0;
    int k2 = 0;
    int j1 = 0;
    int j2 = 0;
    int ok1 = 0;
    int ok2 = 0;

    System.out.println(old.toString());
    System.out.println("haha");
    System.out.println(curent.toString());

    i1 = i2 = 0;
    while(i1 < n && i2 < n && curent.get(i1)!=null && old.get(i2)!=null) {
            if(!curent.get(i1).equals(old.get(i2))) {
            	
            	/*
            	ok1 = 0;
            	for(int i=i1+1;i<n && old.get(i) != null;i++) {
            		if(curent.get(i1).equals(old.get(i))) {
            			ok1 = 1;
            			break;
            		}
            	}
            	ok2 = 0;
            	for(int i=i1+1;i<n && old.get(i) != null;i++) {
            		if(curent.get(i1).equals(old.get(i))) {
            			ok1 = 1;
            			break;
            		}
            	}
            	
            	if(!curent.containsValue(old.get(i2)) || !old.containsValue(curent.get(i1))) {
            		diff++;
            	}
            	else
            	{
            	*/
            	
                    //System.out.println(i1+" "+i2);
                    j1 = i1 + 1;
                    j2 = i2 + 1;
                    
                    while(j1 < n && j2 < n && curent.get(j1)!=null && old.get(j2)!=null) {

                            if(curent.get(i1).equals(old.get(j2))) {
                                    //System.out.println("Versiunea actuala :  " + old.get(i2) + "   " + i2);
                                    for(int l=i2;l<j2;l++) {
                                        versiuneCurenta.put(l, old.get(l));  
                                    }
                                    i2 = j2;
                                    break;
                            }
                            if(old.get(i2).equals(curent.get(j1))) {
                                    //System.out.println("Versiunea veche :  " + curent.get(i1) + "   " + i1);
                                    for(int l=i1;l<j1;l++) {
                                    	versiuneVeche.put(l, curent.get(l));
                                    }
                                    i1 = j1;
                                    break;
                            }
                            if(old.get(j2).equals(curent.get(j1))) {
                            	for(int l=i1;l<j1;l++) {
                            		versiuneVeche.put(l, curent.get(l));
                            	}
                            	
                            	for(int l=i2;l<j1;l++) {
                            		versiuneCurenta.put(l, old.get(l));
                            	}
                            	i1 = j1;
                            	i2 = j2;
                            	break;
                            }
                            j1 ++;
                            j2 ++;

                    }





                    if(j1 == n || j2 == n) {
	                	versiuneCurenta.put(i2, old.get(i2));
                		versiuneVeche.put(i1, curent.get(i1));
                    }
            	}
            i1 ++;
            i2 ++;

    }


    if(i1 > i2) {

            while(old.get(i2) !=null) {
            	versiuneCurenta.put(i2, old.get(i2));
                i2++;
            }
    }
    else if(i2 > i1) {
            while(curent.get(i1) !=null) {
            	versiuneVeche.put(i1, curent.get(i1));
                i1++;
            }
    }
    if(i1 == i2) {
    	if(curent.size() > old.size()) {
    		while(curent.get(i1) != null) {
    			versiuneVeche.put(i1, curent.get(i1));
    			i1++;
    		}
    	}
    	else {
    		if(old.size() > curent.size()) {
    			while(old.get(i2) != null) {
    				versiuneCurenta.put(i2, old.get(i2));
    				i2++;
    			}
    		}
    	}
    }


        	 try 
             { 
                 FileOutputStream fileOutputStream = new FileOutputStream(indexLocation1+"\\versiuneVeche"); 
                 ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); 
                 objectOutputStream.writeObject(versiuneVeche); 
                 objectOutputStream.flush(); 
                 objectOutputStream.close(); 
                 } 
                 catch(Exception e) { 
                 System.out.println("Exception during serialization: " + e); 
                 System.exit(0); 
             } 
        	 
        	 try 
             { 
                 FileOutputStream fileOutputStream = new FileOutputStream(indexLocation1+"\\versiuneCurenta"); 
                 ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream); 
                 objectOutputStream.writeObject(versiuneCurenta); 
                 objectOutputStream.flush(); 
                 objectOutputStream.close(); 
                 } 
                 catch(Exception e) { 
                 System.out.println("Exception during serialization: " + e); 
                 System.exit(0); 
             } 

    }
    
    
    public boolean heavilyModified() throws IOException
    {
    	HashMap<Integer,String> versiuneVeche = new HashMap();
    	HashMap<Integer,String> versiuneCurenta = new HashMap();
        String indexLocation1;
        String indexLocation2;
        
        
        indexLocation1 = data.getAbsolutePath().substring(0,data.getAbsolutePath().lastIndexOf("\\"))+"\\"+Integer.toString(counter-1);
        indexLocation2 = versionList.get(counter-1);
        
System.out.println(indexLocation1);
System.out.println(indexLocation2);
        
            double diff = 0.0;
            double total = 0.0;


            IndexReader reader = DirectoryReader.open(FSDirectory.open(new File(
                            indexLocation1)));
            int docId = reader.getDocCount(indexLocation1);
        int length = 0;
        Terms vector = reader.getTermVector(docId, "contents");
        TermsEnum termsEnum = null;
        termsEnum = vector.iterator(termsEnum);
        HashMap<Integer, String> curent = new HashMap<>();
        BytesRef text = null;
        Vector<String> terms =new Vector();
        while ((text = termsEnum.next()) != null) {
            String term = text.utf8ToString();
            int freq = (int) termsEnum.totalTermFreq();
            DocsAndPositionsEnum docPosEnum = termsEnum.docsAndPositions(null, null, DocsAndPositionsEnum.FLAG_OFFSETS);
            docPosEnum.nextDoc();
            //Retrieve the term frequency in the current document
            freq=docPosEnum.freq();
            for(int j=0; j<freq; j++){
                int position=docPosEnum.nextPosition();
                curent.put(position, term);
            }            
    }
        reader.close();
        

    IndexReader reader1 = DirectoryReader.open(FSDirectory.open(new File(
                            indexLocation2)));

            int docId1 = reader1.getDocCount(indexLocation1);
            Terms vector1 = reader1.getTermVector(docId1, "contents");
            TermsEnum termsEnum1 = null;
            termsEnum1 = vector1.iterator(termsEnum);
            HashMap<Integer, String> old = new HashMap<>();
            BytesRef text1 = null;
            Vector<String> terms1 = new Vector();

            while ((text1 = termsEnum1.next()) != null) {
                    String term1 = text1.utf8ToString();
                    int freq1 = (int) termsEnum1.totalTermFreq();
                    DocsAndPositionsEnum docPosEnum1 = termsEnum.docsAndPositions(null,
                                    null, DocsAndPositionsEnum.FLAG_OFFSETS);
                    docPosEnum1.nextDoc();
                    // Retrieve the term frequency in the current document
                    freq1 = docPosEnum1.freq();
                    for(int j=0; j<freq1; j++){
			            int position=docPosEnum1.nextPosition();
			            old.put(position, term1);
                    }    
            }

            reader1.close();
            /*
            for(int i=0;i<curent.size()+1;i++) {
                    System.out.println(curent.get(i));
            }
            System.out.println("--------------------");
            for(int i=0;i<old.size();i++) {
                    System.out.println(old.get(i));
            }
            */

            int n;
    if(curent.size() >old.size()) {
            n = curent.size();
    } else {
            n = old.size();
    }

    total = curent.size() + old.size();

    int i1;
    int i2;
    int i3;
    int k1 = 0;
    int k2 = 0;
    int j1 = 0;
    int j2 = 0;
    int ok1 = 0;
    int ok2 = 0;

    System.out.println(old.toString());
    System.out.println(curent.toString());

    i1 = i2 = 0;
    while(i1 < n && i2 < n && curent.get(i1)!=null && old.get(i2)!=null) {
            if(!curent.get(i1).equals(old.get(i2))) {
            	
            	/*
            	ok1 = 0;
            	for(int i=i1+1;i<n && old.get(i) != null;i++) {
            		if(curent.get(i1).equals(old.get(i))) {
            			ok1 = 1;
            			break;
            		}
            	}
            	ok2 = 0;
            	for(int i=i1+1;i<n && old.get(i) != null;i++) {
            		if(curent.get(i1).equals(old.get(i))) {
            			ok1 = 1;
            			break;
            		}
            	}
            	
            	if(!curent.containsValue(old.get(i2)) || !old.containsValue(curent.get(i1))) {
            		diff++;
            	}
            	else
            	{
            	*/
            	
                    //System.out.println(i1+" "+i2);
                    j1 = i1 + 1;
                    j2 = i2 + 1;
                    
                    while(j1 < n && j2 < n && curent.get(j1)!=null && old.get(j2)!=null) {

                            if(curent.get(i1).equals(old.get(j2))) {
                                    //System.out.println("Versiunea actuala :  " + old.get(i2) + "   " + i2);
                                    for(int l=i2;l<j2;l++) {
                                    	diff++; 
                                    }
                                    i2 = j2;
                                    break;
                            }
                            if(old.get(i2).equals(curent.get(j1))) {
                                    //System.out.println("Versiunea veche :  " + curent.get(i1) + "   " + i1);
                                    for(int l=i1;l<j1;l++) {
                                    	diff++;
                                    }
                                    i1 = j1;
                                    break;
                            }
                            if(old.get(j2).equals(curent.get(j1))) {
                            	for(int l=i1;l<j1;l++) {
                            		diff++;
                            	}
                            	
                            	for(int l=i2;l<j1;l++) {
                            		diff++;
                            	}
                            	i1 = j1;
                            	i2 = j2;
                            	break;
                            }
                            j1 ++;
                            j2 ++;

                    }






                    if(j1 == n || j2 == n) {
                    	diff++;
	                	diff++;
                    }
            	}
            i1 ++;
            i2 ++;

    }


    if(i1 > i2) {

            while(old.get(i2) !=null) {
                diff++;
                i2++;
            }
    }
    else if(i2 > i1) {
            while(curent.get(i1) !=null) {
                diff++;
                i1++;
            }
    }
    if(i1 == i2) {
    	if(curent.size() > old.size()) {
    		while(curent.get(i1) != null) {
    			diff++;
    			i1++;
    		}
    	}
    	else {
    		if(old.size() > curent.size()) {
    			while(old.get(i2) != null) {
    				diff++;
    				i2++;
    			}
    		}
    	}
    }
        System.out.println("aici diferente "+diff+" "+total);
        System.out.println(versiuneVeche.toString());
        System.out.println(versiuneCurenta.toString());

        if(diff/total*100 > 50 || diff/total*100 == 0.0) {
            return true;
        } else {
            return false;
        }

    }
    
    public void CreateIndex(String filePath, String newPath) throws IOException
    {
        String indexPath = newPath + "\\" + Integer.toString(counter); // locatia unde se indexeaza
        boolean tst = (new File(indexPath)).mkdir();
        System.out.println("Directory: " + indexPath + " created");   
        
        final File doc;
        if(this.getData().toString().substring(this.getData().toString().lastIndexOf(".")+1, this.getData().toString().length()).equals("html")) {
        	doc = new File(this.getData().toString());
        	System.out.println("am intrat aici");
        } else {
        	doc = new File(filePath);
        }

        recurrence (indexPath ,doc ,true);
        
        File source = new File(doc.toString());
		File destination = new File(indexPath+"\\"+doc.getName());
		
		
		InputStream inStream = new FileInputStream(source);
		OutputStream outStream = new FileOutputStream(destination);
		int length;
		byte[] buffer = new byte[1024];
		while((length = inStream.read(buffer)) > 0) {
			outStream.write(buffer,0,length);
		}				
		inStream.close();
		outStream.close();

    }
    
    private static void recurrence(String path, File file, boolean create) throws IOException
    {
        if (file.canRead()) 
        {
            if (file.isDirectory()) 
            {
                System.out.println("IS DIRECTORY!");
                System.exit(1);
            } 
            else 
            {
                //String path = indexPath;// + "\\" + file.getName();
                System.out.println("Directory: " + path + " created");    
                Directory dir = FSDirectory.open(new File(path));
                Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_40,CharArraySet.EMPTY_SET);
                IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_40, analyzer);
                if (create) 
                {
                    iwc.setOpenMode(OpenMode.CREATE);System.out.println("asdasd");
                } 
                else 
                {
                    iwc.setOpenMode(OpenMode.CREATE_OR_APPEND);System.out.println("asdasd");
                }
                System.out.println("asdasd");
                IndexWriter writer = new IndexWriter(dir, iwc); 
                    System.out.println("asdasd");
                    FileInputStream fis;
                    System.out.println("asdasd");
                    fis = new FileInputStream(file);

                    //try
                    //{
                    Document doc = new Document();

                    Field pathField = new StringField("path", file.getPath(), Field.Store.YES);
                    doc.add(pathField);
                    doc.add(new LongField("modified", file.lastModified(), Field.Store.NO));
                    doc.add(new Field("contents", new BufferedReader(new InputStreamReader(fis, StandardCharsets.UTF_8)), Field.TermVector.WITH_POSITIONS_OFFSETS ));
                    System.out.println("Asdasd");
                    if (writer.getConfig().getOpenMode() == OpenMode.CREATE)
                    {
                        System.out.println("adding " + file);
                        writer.addDocument(doc);
                        
                    }
                    else
                    {
                        System.out.println("updating " + file);
                        writer.updateDocument(new Term("path", file.getPath()), doc);
                        new File(path);
                    }
                    //}
                   // finally
                   // {
                        fis.close();
                   // }
                       writer.close();
                       
                } 
        }
        else
        {
            System.out.println("wtf man");
        }
    }
}

